package rps.game;

import java.rmi.RemoteException;

import rps.game.data.Figure;
import rps.game.data.FigureKind;
import rps.game.data.Move;
import rps.game.data.Player;

/**
 * This decorator is used to remove all information from get* methods that are
 * not visible for the corresponding player. Most importantly this is the
 * FigureKind of all Figure on the field that are undiscovered yet and do belong
 * to the other player.
 */
public class FigureHidingGame implements Game {

	private final Game game;
	private final Player player;

	public FigureHidingGame(Game game, Player player) throws RemoteException {
		this.game = game;
		this.player = player;
	}

	@Override
	public void setInitialAssignment(Player p, FigureKind[] assignment) throws RemoteException {
		if (p.equals(player))
			game.setInitialAssignment(p, assignment);
		else
			game.setInitialAssignment(p, hideFigureKind(assignment));
	}

	@Override
	public Figure[] getField() throws RemoteException {
		//return the decorated field
		return decorateField(game.getField(), player);
	}

	@Override
	public void move(Player p, int from, int to) throws RemoteException {
		game.move(p, from, to);
	}

	@Override
	public Move getLastMove() throws RemoteException {
		//get the undecorated move
		Move move = game.getLastMove();
		//replace the undecorated field in the move object with a decorated one
		Move newMove = new Move(move.getFrom(), move.getTo(), decorateField(move.getOldField(), player));
		
		return newMove;
	}

	@Override
	public void sendMessage(Player p, String message) throws RemoteException {
		game.sendMessage(p, message);
	}

	@Override
	public void setInitialChoice(Player p, FigureKind kind) throws RemoteException {
		if (p.equals(player))
			game.setInitialChoice(p, kind);
		else
			game.setInitialChoice(p, FigureKind.HIDDEN);
	}

	@Override
	public void setUpdatedKindAfterDraw(Player p, FigureKind kind) throws RemoteException {
		if (p.equals(player))
			game.setUpdatedKindAfterDraw(p, kind);
		else
			game.setUpdatedKindAfterDraw(p, FigureKind.HIDDEN);
	}

	@Override
	public void surrender(Player p) throws RemoteException {
		game.surrender(p);
	}

	@Override
	public Player getOpponent(Player p) throws RemoteException {
		return game.getOpponent(p);
	}
	
	/**
	 * replaces all undiscovered pieces with hidden figurekind
	 * @param field the field to decorate
	 * @param p the player who requests the field
	 * @return the decorated field
	 * @throws RemoteException
	 */
	private Figure[] decorateField(Figure[] field, Player p) throws RemoteException {
		//loop through all fields
		for (int i=0; i<field.length; i++) {
			if (field[i] != null) {
				//if a figure does not belong to the requesting player and is not yet discovered
				//it gets replaced by a hidden figure
				if (!field[i].belongsTo(p) && !field[i].isDiscovered()) {
					field[i] = new Figure(FigureKind.HIDDEN, getOpponent(p));
				}
			}
		}
		
		return field;
	}
	
	/**
	 * replaces all figurekinds in the given array with hidden figurekinds
	 * @param figures array to decorate
	 * @return decorated array
	 */
	private FigureKind[] hideFigureKind(FigureKind[] figures) {
		for (int i=0; i<figures.length; i++) {
			if (figures[i] != null) {
				figures[i] = FigureKind.HIDDEN;
			}
		}
		return figures;
	}
}